﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AliboboStockLib.linq;
using AliboboStockLib.date;
using System.Collections;
using System.Data.Common;
using AliboboStockLib.util;
using System.Data;
using AliboboStockLib.fetcher;
using AliboboStockLib.stockdata.inst;

namespace AliboboStockLib.stockupdater.sbdetail
{
    public abstract class SBDetailUpdater
    {
        public abstract String getMarketName();
        protected static MyStockDataContext getContext()
        {
            MyStockDataContext context = LinqAgent.getContext();
            return context;
        }

        protected static HashSet<String> filterToCreate(List<String> exists, List<String> allCodes)
        {
            HashSet<String> createdCodes = new HashSet<string>(exists);
            HashSet<String> toCreate = new HashSet<String>();
            if (createdCodes.Count == 0)
            {
                foreach (String s in allCodes)
                    toCreate.Add(s);
            }
            else
            {
                if (allCodes.Count != createdCodes.Count)
                {
                    foreach (String code in allCodes)
                    {
                        if (createdCodes.Contains(code))
                            continue;
                        toCreate.Add(code);
                    }
                }
            }
            return toCreate;
        }

        protected static int createSBTask(HashSet<String> codes, DateTime date, String market)
        {
            DateTime now = DateTime.Now;
            MyStockDataContext context = LinqAgent.getContext();
            foreach (String code in codes)
            {
                SBDataTask task = new SBDataTask();
                task.日期 = date;
                task.StockCode = code;
                task.state = 1;
                task.SBId = NewGUID.create("sbtk");
                task.lastprocessTime = now;
                task.market = market;
                context.SBDataTasks.InsertOnSubmit(task);
            }
            context.SubmitChanges();
            return codes.Count;
        }

        protected abstract void prepareSBTask(DateTime d);

        protected List<SBRecordState> getCurrentSBStates_internal(DateTime d, String market)
        {
            prepareSBTask(d);
            List<SBRecordState> result = new List<SBRecordState>();

            String sql = "SELECT SBDataTask.StockCode, SBDataTask.state, SBDataTask.lastprocessTime, SBDataTask.SBId, SBDataTask.日期, StockIndex.名稱 " +
            "FROM  SBDataTask INNER JOIN   StockIndex ON SBDataTask.StockCode = StockIndex.代號   " +
            "WHERE (StockIndex.市場 = N'" + market + "') AND (SBDataTask.日期 = @date)";

            DbCommand cmd = SQLFactory.getInstance(0).getCommand();
            cmd.CommandText = sql;
            DbParameter pd = SQLFactory.getInstance(0).createParam("@date", DbType.Date, d);
            cmd.Parameters.Add(pd);
            DbDataReader reader = cmd.ExecuteReader();
            Hashtable ht = new Hashtable();

            while (reader.Read())
            {
                SBRecordState state = new SBRecordState();
                state.代號 = reader.GetString(0);
                String ss = reader.GetValue(1).ToString();
                int i;
                if (int.TryParse(ss, out i))
                {
                    state.處理進度 = (SBTaskState)i;
                }
                else
                {
                    state.處理進度 = SBTaskState.待處理;
                }
                //------------
                ss = reader.GetValue(2).ToString();
                DateTime pdd = DateTime.Now;
                if (DateTime.TryParse(ss, out  pdd))
                {
                    state.處理時間 = DateUtils.getYYYYMMDDHHSS(pdd);
                }
                else
                    state.處理時間 = "";
                state.taskId = reader.GetGuid(3);
                state.名稱 = reader.GetString(5);
                ht.Add(state.代號, state);
                result.Add(state);
            }
            reader.Close();
            cmd.Dispose();

            //------------------------------------------------------------------------------------
            try
            {
                String sql2 = "SELECT  證券代號, 成交股數, 成交筆數, 成交金額, 收盤價, 日期 " +
                                      "FROM      StockDaily where 日期 = @date ";

                cmd = SQLFactory.getInstance(0).getCommand();
                cmd.CommandText = sql2;

                pd = SQLFactory.getInstance(0).createParam("@date", DbType.Date, DateUtils.getSlashYYYYMMDD(d));
                cmd.Parameters.Add(pd);

                reader = cmd.ExecuteReader();

                decimal localdec = new decimal(0);
                while (reader.Read())
                {
                    String code = reader.GetString(0);
                    if (ht.Contains(code) == false)
                        continue;
                    SBRecordState state = (SBRecordState)ht[code];
                    state.成交股數 = reader.GetInt32(1);
                    state.交易筆數 = reader.GetInt32(2);
                    state.交易金額 = reader.GetDecimal(3);
                    String ps = reader.GetValue(4).ToString();

                    //當沒有交易的時候 股數 比數 金額 會=0 但是股價是空
                    //state.股價 = reader.GetDecimal(4);
                    if (decimal.TryParse(ps, out localdec))
                    {
                        state.股價 = localdec;
                    }

                }
                reader.Dispose();
                cmd.Dispose();
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.StackTrace);
                System.Diagnostics.Debug.WriteLine(e.Message);

            }
            return result;
        }

        public void updateTaskState(Guid taskId, SBTaskState state, DateTime d)
        {
            String sql = "update SBDataTask set  state =@state, lastprocessTime = @procTime  where SBID= @id";
            int s = (int)state;
            DbCommand cmd = SQLFactory.getInstance(0).getCommand();
            cmd.CommandText = sql;
            cmd.Parameters.Add(SQLFactory.getInstance(0).createParam("@state", DbType.Int32, (int)s));

            DbParameter dp = SQLFactory.getInstance(0).createParam("@procTime", System.Data.DbType.DateTime, d);
            cmd.Parameters.Add(dp);

            DbParameter p = SQLFactory.getInstance(0).createParam("@id", DbType.Guid, taskId);
            cmd.Parameters.Add(p);
            int cc = cmd.ExecuteNonQuery();
            cmd.Dispose();
        }


        protected static void deleteSBDetails(Guid taskId)
        {
            //先刪除
            String sql = "delete from SBDetails where taskId=@id";
            DbCommand cmd = SQLFactory.getInstance(0).getCommand();
            cmd.CommandText = sql;
            DbParameter p = SQLFactory.getInstance(0).createParam("@id", DbType.Guid, taskId);
            cmd.Parameters.Add(p);
            int deleted = cmd.ExecuteNonQuery();
            cmd.Parameters.Clear();
            cmd.Dispose();
        }
        protected int selectOldCount(String stockCode, DateTime d)
        {
            string sql = "select count(*) as c from SBDetails where StockCode='" + stockCode + "' and 日期='" + DateUtils.getSlashYYYYMMDD(d) + "'; ";
            MyStockDataContext context = LinqAgent.getContext();
            var c = context.ExecuteQuery<int>(sql).FirstOrDefault();
            return Convert.ToInt32(c);
        }

        public void updateSBDetails(List<SBEntry> SBEntries, Guid taskId, String stockCode, DateTime d)
        {
            if (SBEntries == null)
                return;
            if (SBEntries.Count == 0)
                return;
            int oldc = selectOldCount(stockCode, d);
            if((oldc>0)&& (oldc != SBEntries.Count))
                deleteSBDetails(taskId);

            //更新機構

            foreach (SBEntry e in SBEntries)
            {
                Guid instId = Guid.Empty;
                if (TradeInstManager.getInstId(e.instCode, out instId))
                    e.instId = instId;
                else
                    e.instId = TradeInstManager.registerInst(e.instCode, e.instName);
            }
            //---->
            InsertSBDetails(SBEntries, taskId, stockCode, d);

        }
        protected static void InsertSBDetails(List<SBEntry> SBEntries, Guid taskId, String stockCode, DateTime d)
        {
            //int step = 10;
            //-----------組合
            DbTransaction transaction = SQLFactory.getInstance(0).BeginTransation();
            DbCommand cmd = SQLFactory.getInstance(0).getCommand();
            cmd.Transaction = transaction;
            cmd.CommandText = "Insert into SBDetails ( taskId,seq,instId,price,buy,sell ,日期,StockCode) values (@taskId,@seq,@instId,@price,@buy,@sell ,@date,@stockCode)";
            DbParameter taskIdP = SQLFactory.getInstance(0).createParam("@taskId", DbType.Guid, null);
            DbParameter seqP = SQLFactory.getInstance(0).createParam("@seq", DbType.Int32, null);
            DbParameter instIdP = SQLFactory.getInstance(0).createParam("@instId", DbType.Guid, null);
            DbParameter priceP = SQLFactory.getInstance(0).createParam("@price", DbType.Decimal, null);
            DbParameter buyP = SQLFactory.getInstance(0).createParam("@buy", DbType.Int32, null);
            DbParameter sellP = SQLFactory.getInstance(0).createParam("@sell", DbType.Int32, null);

            DbParameter 日期P = SQLFactory.getInstance(0).createParam("@date", DbType.Date, d);
            DbParameter stockCodeP = SQLFactory.getInstance(0).createParam("@stockCode", DbType.String, stockCode);




            cmd.Parameters.Add(taskIdP);
            cmd.Parameters.Add(seqP);
            cmd.Parameters.Add(instIdP);
            cmd.Parameters.Add(priceP);
            cmd.Parameters.Add(buyP);
            cmd.Parameters.Add(sellP);

            cmd.Parameters.Add(日期P);
            cmd.Parameters.Add(stockCodeP);



            cmd.Parameters[0].Value = taskId;
            foreach (SBEntry sb in SBEntries)
            {
                cmd.Parameters[1].Value = sb.seq;
                cmd.Parameters[2].Value = sb.instId;
                cmd.Parameters[3].Value = sb.price;
                cmd.Parameters[4].Value = sb.buy;
                cmd.Parameters[5].Value = sb.sell;
                cmd.ExecuteNonQuery();
            }
            transaction.Commit();
            cmd.Dispose();
            transaction.Dispose();
        }

        protected int createSBTask(HashSet<String> codes, DateTime date)
        {
            return createSBTask(codes, date, getMarketName());
        }

        public List<SBRecordState> getCurrentSBStates(DateTime d)
        {
            return getCurrentSBStates_internal(d, getMarketName());
        }

    }
}
